package traveldream.ejb.packetmanagement;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Date;

import javax.annotation.Resource;
import javax.ejb.EJB;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import traveldream.ejb.packetmanagement.PacketMgr;
import traveldream.ejb.packetmanagement.dto.PacketDTO;

/**
 * Session Bean implementation class PacketMgr
 */
@Stateless
public class PacketMgrBean implements PacketMgr {
	
    public PacketMgrBean() {
    }

    @PersistenceContext
    private EntityManager em;
	
	@Resource
	private EJBContext context;
	
	@Override
	public List<PacketDTO> findByPid(long pid){
		List<PacketDTO> listToReturn = new ArrayList<PacketDTO>();
		List<PacchettoViaggio> packetList = findPacketByPid(pid);
		for(int i=0; i<packetList.size(); i++){
			listToReturn.add(convertToDTO(packetList.get(i)));
		}
		return listToReturn;
	}
	
	@Override
	public List<PacketDTO> findByDestinazione(String dest){
		List<PacketDTO> listToReturn = new ArrayList<PacketDTO>();
		List<PacchettoViaggio> packetList = findPacketByDestination(dest);
		for(int i=0; i<packetList.size(); i++){
			listToReturn.add(convertToDTO(packetList.get(i)));
		}
		return listToReturn;
	}
	
	//Ricerca tutti i pacchetti successivi alla data fornita in ingresso
	@Override
	public List<PacketDTO> findByDate(Date data){
		List<PacketDTO> listToReturn = new ArrayList<PacketDTO>();
		List<PacchettoViaggio> packetList = findPacketByDate(data);
		for(int i=0; i<packetList.size(); i++){
			listToReturn.add(convertToDTO(packetList.get(i)));
		}
		return listToReturn;
	}
	
	@Override
	public List<PacketDTO> findCombo(String destinazione, Date data){
		List<PacketDTO> listToReturn = new ArrayList<PacketDTO>();
		List<PacchettoViaggio> packetList = findPacketCombo(destinazione, data);
		for(int i=0; i<packetList.size(); i++){
			listToReturn.add(convertToDTO(packetList.get(i)));
		}
		return listToReturn;
	}
	
	private List<PacchettoViaggio> findPacketByPid(long pid){
		Query q;
		q= em.createNamedQuery(PacchettoViaggio.FIND_BY_PID , PacchettoViaggio.class);
		q.setParameter(1, pid);
		return q.getResultList();
	}

	private List<PacchettoViaggio> findPacketByDestination(String destinazione){
		Query q;
		q= em.createNamedQuery(PacchettoViaggio.FIND_BY_DEST, PacchettoViaggio.class);
		q.setParameter(1, destinazione);
		return q.getResultList();
	}
	
	private List<PacchettoViaggio> findPacketByDate(Date data){
		Query q;
		q= em.createNamedQuery(PacchettoViaggio.FIND_BY_DATE, PacchettoViaggio.class);
		q.setParameter(1, data);
		return q.getResultList();
	}
	
	private List<PacchettoViaggio> findPacketCombo(String destinazione, Date data){
		Query q;
		q= em.createNamedQuery(PacchettoViaggio.FIND_COMBO, PacchettoViaggio.class);
		q.setParameter(1, destinazione);
		q.setParameter(2, data);
		return q.getResultList();
	}
	
	private PacketDTO convertToDTO(PacchettoViaggio pack){
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		PacketDTO packetDTO = new PacketDTO();
		packetDTO.setPid(pack.getPID());
		packetDTO.setVidAndata(pack.getVoloAndata().getVID());
		packetDTO.setVidRitorno(pack.getVoloRitorno().getVID());
		packetDTO.setHidHotel(pack.getHotel().getHID());
		List<Long> listaXids = new ArrayList<Long>();
		for(int i=0; i<pack.getEscursioni().size(); i++){
			listaXids.add(pack.getEscursioni().get(i).getXID());
		}
		packetDTO.setXidEscursioni(listaXids);
		packetDTO.setCostoTotale(pack.getCostoTotale());
		packetDTO.setDataInizio(dateFormat.format(pack.getDataInizio()));
		packetDTO.setDataFine(dateFormat.format(pack.getDataFine()));
		packetDTO.setDestinazione(pack.getDestinazione());
		return packetDTO;
	}

	
	public PacchettoViaggio convertToClass(PacketDTO packetDTO){
		Query q;
		Date dataInizio= new Date(); Date dataFine=new Date();
		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		float costoTotale = packetDTO.getCostoTotale();
		String destinazione = packetDTO.getDestinazione();
		try {
			dataInizio = dateFormat.parse(packetDTO.getDataInizio());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		try {
			dataFine = dateFormat.parse(packetDTO.getDataFine());
		} catch (ParseException e) {
			e.printStackTrace();
		}
		q = em.createNamedQuery(Hotel.FIND_BY_HID, Hotel.class);
		q.setParameter(1, packetDTO.getHidHotel());
		List<Hotel> resList = q.getResultList();
		Hotel hotel = resList.get(0);
		q = em.createNamedQuery(Volo.FIND_BY_VID, Volo.class);
		q.setParameter(1, packetDTO.getVidAndata());
		List<Volo> resList2 = q.getResultList();
		Volo voloAndata = resList2.get(0);
		q = em.createNamedQuery(Volo.FIND_BY_VID, Volo.class);
		q.setParameter(1, packetDTO.getVidRitorno());
		List<Volo> resList3 = q.getResultList();
		Volo voloRitorno= resList3.get(0);
		List<Escursione> escursioni =new ArrayList<Escursione>();
		List<Escursione> resList4 = new ArrayList<Escursione>();
		for(int i=0; i<packetDTO.getXidEscursioni().size(); i++){
		q = em.createNamedQuery(Escursione.FIND_BY_XID, Escursione.class);
		q.setParameter(1, packetDTO.getXidEscursioni().get(i));
		resList4 = q.getResultList();
		escursioni.add(resList4.get(0));
		}
		return new PacchettoViaggio(destinazione, dataInizio, dataFine,costoTotale,
									voloAndata, voloRitorno, hotel, escursioni);
		
	}
	
	@Override
	public long savePacket(PacketDTO packetDTO) {
		PacchettoViaggio p = convertToClass(packetDTO);
		em.persist(p);
		em.flush();
		return p.getPID();
		}

	@Override
	public boolean addable(PacketDTO packet) {
		int counter=0;
		PacchettoViaggio pack = convertToClass(packet);
		Query q = em.createNamedQuery(PacchettoViaggio.FIND_DUPLICATE, PacchettoViaggio.class);
		q.setParameter(1, packet.getDestinazione());
		q.setParameter(2, pack.getDataInizio());
		q.setParameter(3, pack.getDataFine());
		q.setParameter(4, pack.getCostoTotale());
		q.setParameter(5, pack.getVoloAndata());
		q.setParameter(6, pack.getVoloRitorno());
		q.setParameter(7, pack.getHotel());
		if(q.getResultList().size()==0)
			return true;
		else{
			List<PacchettoViaggio> resList = q.getResultList();
			Query m=em.createNamedQuery(Escursione.FIND_BY_PID, Escursione.class);
			m.setParameter(1, resList.get(0).getPID());
			List<Escursione> listaCritica = m.getResultList();
			for(int i=0; i<listaCritica.size(); i++){
				for(int j=0; j<packet.getXidEscursioni().size(); j++)
					if(listaCritica.get(i).getXID()==packet.getXidEscursioni().get(j))
						counter= counter+1;
			}
			if(counter==listaCritica.size() && counter==packet.getXidEscursioni().size())
				return false;
			else
				return true;
		}
	}
	
	@Override
	public float calculatePacketCost(PacketDTO packetDTO){
			float costo;
			PacchettoViaggio packet = convertToClass(packetDTO);
			GregorianCalendar c1, c2;
			c1= new GregorianCalendar();
			c2 = new GregorianCalendar();
			float durataHotel, durataHotelMills;
			c1.setTime(packet.getVoloAndata().getDataArrivo());
			c2.setTime(packet.getVoloRitorno().getDataPartenza());
			durataHotelMills = c2.getTimeInMillis() - c1.getTimeInMillis();
			durataHotel = durataHotelMills /86400000;
			costo = packet.getVoloAndata().getCostoBiglietto() + packet.getVoloRitorno().getCostoBiglietto() + 
					packet.getHotel().getCostoPerGiorno()*durataHotel;
			for(int i=0; i<packet.getEscursioni().size(); i++){
				costo = costo + packet.getEscursioni().get(i).getCostoEx();
			}
			return costo;
			
	}
	
	
	
}
	
